<script setup>
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader'
import { onMounted, ref } from 'vue'

const props = defineProps({
  gltfUrl: {
    type: String,
    default: ''
  },
  sceneBackground: {
    type: String,
    default: '#123456'
  },
  cameraZ: {
    type: Number,
    default: -100
  },
  minDistance: {
    type: Number,
    default: 100
  },
  maxDistance: {
    type: Number,
    default: 1000
  },
  productName: {
    type: String,
    default: ''
  }
})
// const animDuration = ref(0)
// 模型是否打开
const yinmuOpened = ref(false)
// const startView = ref()
const threeView = ref(null)
let scene,
  camera,
  clock,
  loader,
  controls,
  mixer,
  renderer,
  model,
  actions = []
// actionsBack = []

onMounted(() => {
  scene = new THREE.Scene()
  scene.background = new THREE.Color(props.sceneBackground)
  camera = new THREE.PerspectiveCamera(
    75,
    threeView.value.offsetWidth / threeView.value.offsetHeight,
    0.1,
    1000
  )

  const directionalLight = new THREE.AmbientLight(0xffffff, 5)
  scene.add(directionalLight)
  // 时间控制器
  clock = new THREE.Clock()
  loader = new GLTFLoader()
  loader.load(
    props.gltfUrl,
    function (gltf) {
      model = gltf.scene
      scene.add(model)
      // 创建动画混合器
      mixer = new THREE.AnimationMixer(model)
      // 获取所有动画剪辑并播放第一个动画
      gltf.animations.forEach((clip) => {
        const action = mixer.clipAction(clip)
        // 设置动画不循环
        action.setLoop(THREE.LoopOnce)
        action.clampWhenFinished = true // 确保动画结束后保持最后一帧
        actions.push(action) // 将动作添加到数组中
      })
    },
    undefined,
    function (error) {
      console.error('An error happened', error) // 添加错误处理
    }
  )
  camera.position.set(0, 0, props.cameraZ)

  renderer = new THREE.WebGLRenderer()
  renderer.setSize(threeView.value.offsetWidth, threeView.value.offsetHeight)
  renderer.setPixelRatio(window.devicePixelRatio)
  controls = new OrbitControls(camera, renderer.domElement)
  controls.maxDistance = props.maxDistance
  controls.minDistance = props.minDistance
  // controls.target = new THREE.Vector3(0,0,0)
  controls.update()
  if (threeView.value) {
    // 确保threeView已经正确绑定到DOM元素
    threeView.value.appendChild(renderer.domElement)
  }
  animate()
})
// function animate() {
//   requestAnimationFrame(animate)
//   if (mixer) {
//     console.log('Updating mixer...')
//     mixer.update(clock.getDelta())
//   }
//   renderer.render(scene, camera)
//   controls.update()
// }
let openResolve, closeResolve
let allActionsFinished = () => {
  return actions.every(
    (action) =>
      (action.time >= action.getClip().duration && action.timeScale === 1) ||
      (action.time <= 0 && action.timeScale === -1)
  )
}

async function playOpenAnim() {
  if (!yinmuOpened.value) {
    const promise = new Promise((resolve) => (openResolve = resolve))
    actions.forEach((action) => {
      action.reset()
      action.time = 0
      action.timeScale = 1
      action.play()
      console.log(`Playing action: ${action.getClip().name}`)
    })

    yinmuOpened.value = true // 可以根据需求调整这个位置

    await promise
    console.log('yinmuOpened.value', yinmuOpened.value)
    yinmuOpened.value = true // 确保在动画完成后设置为true
    console.log('yinmuOpened.value', yinmuOpened.value)
  }
}

async function playCloseAnim() {
  if (yinmuOpened.value) {
    const promise = new Promise((resolve) => (closeResolve = resolve))
    actions.forEach((action) => {
      action.reset()
      action.time = action.getClip().duration
      action.timeScale = -1
      action.play()
      console.log(`Playing action in reverse: ${action.getClip().name}`)
    })

    yinmuOpened.value = false // 可以根据需求调整这个位置

    await promise
    console.log('yinmuOpened.value', yinmuOpened.value)
    yinmuOpened.value = false // 确保在动画完成后设置为false
    console.log('yinmuOpened.value', yinmuOpened.value)
  }
}

function animate() {
  requestAnimationFrame(animate)
  if (mixer) {
    mixer.update(clock.getDelta())
    if (openResolve && allActionsFinished()) {
      openResolve()
      openResolve = null
    }
    if (closeResolve && allActionsFinished()) {
      closeResolve()
      closeResolve = null
    }
  }
  renderer.render(scene, camera)
  controls.update()
}
// function resetControls() {
//   controls.reset()
// }
</script>

<template>
  <div ref="threeView" class="threejs_container">
    <div class="playanimationopen" @click="playOpenAnim">打开动画</div>
    <div class="playanimationclose" @click="playCloseAnim">关闭动画</div>
  </div>
</template>

<style lang="scss" scoped>
.threejs_container {
  width: 100%;
  height: 100%;
  position: relative;
  .playanimationopen {
    width: 6vw;
    height: 2vw;
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    right: 1vw;
    top: 1vw;
    background-color: antiquewhite;
    color: red;
  }
  .playanimationclose {
    width: 6vw;
    height: 2vw;
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    right: 1vw;
    top: 4vw;
    background-color: antiquewhite;
    color: green;
  }
}
</style>
